package main

import (
	"fmt"
	"net/http"
)

const (
	ProlongationPeriod   = 607875500 // ms
	ObtainTicketResponse = `
<ObtainTicketResponse>
	<message></message>
	<prolongationPeriod>%d</prolongationPeriod>
	<responseCode>OK</responseCode>
	<salt>%s</salt>
	<ticketId>1</ticketId>
	<ticketProperties>licensee=%s	licenseType=0	</ticketProperties>
</ObtainTicketResponse>
`
	PingTicketResponse = `
<PingResponse>
	<message></message>
	<responseCode>OK</responseCode>
	<salt>%s</salt>
</PingResponse>
`
	ProlongTicket = `
<ProlongTicketResponse>
	<message></message>
	<responseCode>OK</responseCode>
	<salt>%s</salt>
	<ticketId>1</ticketId>
</ProlongTicketResponse>
`
	ReleaseTicket = `
<ReleaseTicketResponse>
	<message></message>
	<responseCode>OK</responseCode>
	<salt>%s</salt>
</ReleaseTicketResponse>
`
)

func RunHTTPServer() {
	http.HandleFunc("/rpc/obtainTicket.action", obtainTicketHandler)
	http.HandleFunc("/rpc/releaseTicket.action", releaseTicketHandler)
	http.HandleFunc("/rpc/ping.action", pingTicketHandler)
	http.HandleFunc("/rpc/prolongTicket.action", prolongTicketHandler)
	http.HandleFunc("/product", productHandler)
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		// root Handler
		logger.Debugf(
			"RootHandler recieve(client_ip: %s, method: %s, request_uri: %s, headers: %s)",
			r.RemoteAddr, r.Method, r.RequestURI, r.Header,
		)
		w.Write([]byte(fmt.Sprintf("Jetbrains License Server %s", Version)))
	})

	var addr string = config.Host
	if config.Port != 80 {
		addr += fmt.Sprintf(":%d", config.Port)
	}
	logger.Infof("HTTP Server Start and Listen on: http://%s", addr)
	if err := http.ListenAndServe(addr, nil); err != nil {
		logger.Fatal(err.Error())
	}
}

func releaseTicketHandler(w http.ResponseWriter, r *http.Request) {
	logger.Debugf(
		"ReleaseTicket recieve(client_ip: %s, method: %s, request_uri: %s, headers: %s)",
		r.RemoteAddr, r.Method, r.RequestURI, r.Header,
	)
	logger.Infof("Release Ticket(client_ip: %s)", r.RemoteAddr)
	salt := r.URL.Query().Get("salt")
	str := fmt.Sprintf(ReleaseTicket, salt)
	doResponse(w, str)
}

func obtainTicketHandler(w http.ResponseWriter, r *http.Request) {
	logger.Debugf(
		"ObtainTicket recieve(client_ip: %s, method: %s, request_uri: %s, headers: %s)",
		r.RemoteAddr, r.Method, r.RequestURI, r.Header,
	)
	logger.Infof("Obtain Ticket(client_ip: %s)", r.RemoteAddr)
	salt := r.URL.Query().Get("salt")
	//userName := r.URL.Query().Get("userName")
	str := fmt.Sprintf(ObtainTicketResponse, ProlongationPeriod, salt, config.User)
	doResponse(w, str)
}

func pingTicketHandler(w http.ResponseWriter, r *http.Request) {
	logger.Debugf(
		"PingTicket recieve(client_ip: %s, method: %s, request_uri: %s, headers: %s)",
		r.RemoteAddr, r.Method, r.RequestURI, r.Header,
	)
	salt := r.URL.Query().Get("salt")
	str := fmt.Sprintf(PingTicketResponse, salt)
	doResponse(w, str)
}

func prolongTicketHandler(w http.ResponseWriter, r *http.Request) {
	logger.Debugf(
		"ProlongTicket recieve(client_ip: %s, method: %s, request_uri: %s, headers: %s)",
		r.RemoteAddr, r.Method, r.RequestURI, r.Header,
	)
	logger.Infof("Prolong Ticket(client_ip: %s)", r.RemoteAddr)
	salt := r.URL.Query().Get("salt")
	str := fmt.Sprintf(ProlongTicket, salt)
	doResponse(w, str)
}

func doResponse(w http.ResponseWriter, str string) {
	sign, err := signResponse([]byte(str))
	if err != nil {
		http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
		return
	} else {
		signstr := fmt.Sprintf("<!-- %x -->\n%s", string(sign), str)
		// ok
		w.Write([]byte(signstr))
	}
}
